package cn.wolfcode.car.business.service.impl;

import cn.wolfcode.car.business.domain.Appointment;
import cn.wolfcode.car.business.domain.BusinessStatement;
import cn.wolfcode.car.business.domain.BpmnInfo;
import cn.wolfcode.car.business.domain.BpmnInfo;
import cn.wolfcode.car.business.mapper.BpmnInfoMapper;
import cn.wolfcode.car.business.query.BpmnInfoQuery;
import cn.wolfcode.car.business.query.BpmnInfoQuery;
import cn.wolfcode.car.business.service.IAppointmentService;
import cn.wolfcode.car.business.service.IBusinessStatementService;
import cn.wolfcode.car.business.service.IBpmnInfoService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.config.SystemConfig;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.common.util.file.FileUploadUtils;
import cn.wolfcode.car.shiro.ShiroUtils;
import com.github.pagehelper.PageHelper;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.fileupload.FileUpload;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipInputStream;

@Service
@Transactional
public class BpmnInfoServiceImpl implements IBpmnInfoService {

    @Autowired
    private BpmnInfoMapper bpmnInfoMapper;
    @Autowired
    private RepositoryService repositoryService;

    //分页+过滤
    public TablePageInfo<BpmnInfo> query(BpmnInfoQuery qo) {
        PageHelper.startPage(qo.getPageNum(),qo.getPageSize());
        List<BpmnInfo> bpmnInfos=bpmnInfoMapper.selectForList(qo);
        return new TablePageInfo<>(bpmnInfos);
    }

    @Override
    public BpmnInfo get(Long id) {
        return bpmnInfoMapper.selectByPrimaryKey(id);
    }

    //流程定义信息添加
    public void save(BpmnInfo bpmnInfo) {
        bpmnInfoMapper.insert(bpmnInfo);
    }

    @Override
    public void update(BpmnInfo bpmnInfo) {
        bpmnInfoMapper.updateByPrimaryKey(bpmnInfo);
    }

    @Override
    public void deleteBatch(String ids) {

    }


    @Override
    public List<BpmnInfo> list() {
        return bpmnInfoMapper.selectAll();
    }

    //文件上传，将上传的文件保存在指定磁盘中并返回保存的磁盘路径
    public String upload(MultipartFile file) throws IOException {
        String saveFileName="";
        if(file!=null && file.getSize()>0){
            //1、获取文件的后缀名：也就是zip和bpmn文件才能上传
            String extension = FileUploadUtils.getExtension(file);
            if("zip".equalsIgnoreCase(extension) || "bpmn".equalsIgnoreCase(extension) ){//只保存bpmn和zip文件
                //设置上传的路径并保存源文件，返回文件所在的路径
                saveFileName=FileUploadUtils.upload(SystemConfig.getProfile(),file);
                System.out.println(saveFileName);//2021/10/19/627cce05-b84e-4d68-8e09-f3a0c8396ccd.bpmn
            }else {
                throw new BusinessException("文件格式错误，请选择bpmn和zip类型的文件上传！");
            }
        }else {
            throw new BusinessException("文件不存在或者没有内容，请更换上传文件！");
        }
        return saveFileName;
    }

    //添加自定义流程定义：依赖activiti的流程定义部署（也就是用它部署我们的流程定义信息；bpmn文件）
    public void deploy(String filePath, String bpmnType, String deploymentName, String info) throws FileNotFoundException {
        //1、验证传递的参数
        if(filePath==null || bpmnType==null || deploymentName==null ){
            throw new BusinessException("请传递完整的流程定义部署信息");
        }
        //2、activiti部署我们的bpmn文件
        FileInputStream fis=new FileInputStream(new File(SystemConfig.getProfile(),filePath));//bpmn源文件的位置
        Deployment deployment=null;
        if(filePath.toLowerCase().endsWith(".bpmn")){
            deployment=repositoryService.createDeployment()
                    .addInputStream(filePath,fis)//注意这里的filepath是自定义的资源名称
                    .name(deploymentName)//设置流程定义部署的名字
                    .deploy();
        }else if(filePath.toLowerCase().endsWith(".zip")){
            deployment=repositoryService.createDeployment()
                                .addZipInputStream(new ZipInputStream(fis))
                    .name(deploymentName)
                    .deploy();
        }
        //3、封装我们自定义的流程定义对象BpmnInfo对象，并保存至数据库对应表
        //需要流程定义的id和key
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deployment.getId())
                .latestVersion()
                .singleResult();
        //封装自定义流程定义信息
        BpmnInfo bpmnInfo = new BpmnInfo();
        bpmnInfo.setBpmnType(bpmnType);
        bpmnInfo.setBpmnName(deploymentName);
        bpmnInfo.setInfo(info);

        bpmnInfo.setDeploymentId(deployment.getId());
        bpmnInfo.setDeployTime(deployment.getDeploymentTime());

        bpmnInfo.setActProcessId(processDefinition.getId());
        bpmnInfo.setActProcessKey(processDefinition.getKey());
        //保存
        bpmnInfoMapper.insert(bpmnInfo);

        try {
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //修改自定义流程定义信息：只修改info信息
    public void updateInfo(Long bpmnInfoId, String info) {
        bpmnInfoMapper.updateInfo(bpmnInfoId,info);
    }

    //删除自定义流程定义信息：删除自定义的流程定义信息+依赖的activiti的数据信息+上传的文件（此外还要考虑正在运行中的流程实例中的信息）
    public void delete(Long bpmnInfoId) {
        if(bpmnInfoId==null){
            throw new BusinessException("没有选择删除的流程定义信息！");
        }
        //获取自定义的流程定义信息
        BpmnInfo bpmnInfo = bpmnInfoMapper.selectByPrimaryKey(bpmnInfoId);
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(bpmnInfo.getDeploymentId())
                .latestVersion()
                .singleResult();
        //1、获取activiti流程定义相关信息（这个以后用来获取流程实例，在删除流程定义时，需要将服务套餐的状态初始化为刚开始的）

        //2、删除依赖的activiti中的流程定义相关的表(级联删除)
        repositoryService.deleteDeployment(bpmnInfo.getDeploymentId(),true);
        //3、删除上传到磁盘中的文件(需要activiti流程定义对象中的资源名称)【信息被加载进activiti相关表后，就没有用了】
        File file = new File(SystemConfig.getProfile(),processDefinition.getResourceName());
        if(file.exists()){
            file.delete();
        }
        //4、删除自定义的流程定义信息
        bpmnInfoMapper.deleteByPrimaryKey(bpmnInfoId);
    }

    //根据自定义的流程定义type查询bpmnInfo
    public BpmnInfo queryByType(String car_package) {
        return bpmnInfoMapper.queryByType(car_package);
    }


}
